//
//  main.m
//  08-IOS9新特性(Nullability,泛型,_kindof)
//
//  Created by dllo on 16/7/13.
//  Copyright © 2016年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    Person *per = [[Person alloc] init];
    // 1.nullability
    // nonnull 修饰的属性,不能为空(getter和setter方法)
    NSString *str = nil;
    per.name = str;
    per.name = str;
    [per setName:str];
    per.name = @"张三";
    [per name];
    
    // nullable
    // [per setName:<#(NSString * _Nonnull)#>]
    // [per name];
    per.sex = nil;
    
    // null_resettable
    // [per setFriends:<#(NSArray * _Nullable)#>]
    // [per friends];
    
    // 泛型
    // 带泛型的容器(规定了容器中存储的类型)
    // 声明一个可变数组,内部存放的都是NSString
    // 1. 数组中添加其他类型,会有警告
    // 2. 数组取出来的类型不再是id类型,对应变成声明时的类型
    // 3. 泛型会改变类的一些方法,使与声明的类型相同
    NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"sdfds", nil];
    [array addObject:@""];
//    array.firstObject.length
    
    // 带泛型的字典
    NSMutableDictionary<NSString *, NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"sha", @"name", nil];
    NSInteger number = [dic objectForKey:@"name"].length;
    NSLog(@"%ld", number);
    
    
    // 自定义泛型
    Truck<Person *> *truckPer = [[Truck alloc] init];
    [truckPer addObject:per];
    Person *per1 = [truckPer firstObject];
    NSLog(@"%@", per1);
    Student *stu = [[Student alloc] init];
    stu.stuNumber = @"00001";
    Truck<Student *> *truckStu = [[Truck alloc] init];
    //__covariant使得Person的子类可以添加;
    [truckStu addObject:stu];
    
    // 协变性 与 逆变性
    Truck *truck = nil;
    Truck<NSArray *> *truck1 = nil;
    Truck<NSMutableArray *> *truck2 = nil;
    
    // 大类型(任意类型) 可以给有泛型的赋值
    // 也可以有泛型大类型他赋值
    truck = truck1;
    truck = truck2;
    truck1 = truck;
    truck2 = truck;
    
    // __covariant 协变性 子类在给父类时, 自动强转
    // Truck<NSArray *> Truck<NSMutableArray *>
    truck1 = truck2;
    // __contravariant 逆变性 父类给子类赋值,自动强转(暂时不知应用何处)
//    truck2 = truck1;
    
    // 3.__kindof
    // 加__kindof修饰后, 返回的类型及其子类型, 都可以接收这个返回值
    Truck *truckKindOf = [[Truck alloc] init];
   NSMutableArray *arr = (NSMutableArray *)[truckKindOf returnArray];
    NSMutableArray *arr1 = [truckKindOf returnArray];
    NSMutableArray *arr2 = arr1;
    
    
    
    
    
    
    
    
    
    return 0;
}
